local sets = {}
local gets = {}
Align = {
    name = "align",
    props = {
        _alignPercentX = 0.5,
        _alignPercentY = 0.5,
        _alignOffsetX = 0,
        _alignOffsetY = 0,
        alignDirty = true
    },
    sets = sets,
    gets = gets
}

local function onSetParent(self, parent, old)
    if old then
        old:off(NodeEvent.WidthDirty, self.setAlignDirty, self)
        old:off(NodeEvent.HeightDirty, self.setAlignDirty, self)
    end
    if parent then
        parent:on(NodeEvent.WidthDirty, self.setAlignDirty, self)
        parent:on(NodeEvent.HeightDirty, self.setAlignDirty, self)
        self:setAlignDirty()
    end
end

function Align:ctor()
    if self:hasTag("XController") or self:hasTag("YController") then
        Console.error("Entity:", self.name, "already has XController or YController")
    end
    self:addTags("XController", "YController")
    self:on(NodeEvent.SetParent, onSetParent, self)
    if self.parent then
        onSetParent(self, self.parent)
    end
end

for _, k in ipairs({"alignPercentX", "alignPercentY", "alignOffsetX", "alignOffsetY"}) do
    gets[k] = load([[
        return function(self)
            return self._]]..k..[[
        end
    ]])()

    sets[k] = load([[
        return function(self, key, val)
            self._]]..k..[[ = val
            self:setAlignDirty()
        end
    ]])()

end

function Align:setAlignDirty()
    self.alignDirty = true
end
function Align:updateAlign()
    self:updateAlignX()
    self:updateAlignY()
    self.alignDirty = false
end


function Align:updateAlignX()
    if not self.parent then
        return
    end
    local parent = self.parent
    local parentLeft = - parent.ax * parent.width
    self.x = parentLeft + parent.width * self._alignPercentX + self._alignOffsetX
end



function Align:updateAlignY()
    if not self.parent then
        return
    end
    local parent = self.parent
    local parentTop = - parent.ay * parent.height
    self.y = parentTop + parent.height * self._alignPercentY + self._alignOffsetY
end